<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Administrator;
use App\Models\Role;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class RoleController extends Controller
{
    public function store(Request $request)
    {
        $validator = validator(
            $request->only(['name', 'status', 'remark', 'permissions']),
            [
                'name' => 'required|unique:App\Models\Role,name|max:20',
                'status' => 'in:' . implode(',', [Role::STATUS_NORMAL, Role::STATUS_DISABLE]),
                'remark' => 'max:200',
                'permissions' => 'array'
            ],
            [
                'name.required' => trans('conventional.validator_required', ['field' => trans('noun.role') . trans('noun.name')]),
                'name.unique' => trans('conventional.field', ['field' => trans('noun.role') . trans('noun.name')]),
                'name.max' => trans('conventional.max', ['field' => trans('noun.role') . trans('noun.name'), 'max' => 20]),
                'status.in' => trans('conventional.validator_in', ['field' => trans('noun.status'), 'range' => '']),
                'remark.max' => trans('conventional.max', ['field' => trans('noun.remark'), 'max' => 200]),
                'permissions.array' => trans('conventional.validator_data_format_error', ['field' => trans('noun.permission')]),
            ]
        );
        if (($errors = $validator->errors())->isNotEmpty()) {
            $this->response->errorBadRequest(
                implode(',',
                    array_values(
                        array_map(
                            function ($error) {
                                return $error[0];
                            },
                            $errors->toArray()))));
        }

        try {
            DB::beginTransaction();

            /** @var Role $role */
            $role = Role::create($request->only(['name', 'status', 'remark']));
            $role->givePermissionTo($request->get('permissions'));

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();

            $this->response->errorBadRequest($e->getMessage());
        }

        return $this->response->created(null, $role);
    }

    public function update(Request $request, $id)
    {
        $role = null;
        try {
            DB::beginTransaction();

            $role = Role::query()
                ->withoutGlobalScope('status')
                ->findOrFail($id);

            if (($name = $request->get('name')) && $name !== $role['name']) {
                if (Role::query()->withoutGlobalScope('status')->where('name', $name)->exists()) {
                    $this->response->errorBadRequest('角色名称已存在!');
                }

                $role->name = $name;
            }
            if (($status = (int) $request->get('status')) &&
                in_array($status, [Administrator::STATUS_NORMAL, Administrator::STATUS_DISABLE], true)) {

                $role->status = $status;
            }
            if (null !== ($remark = $request->get('remark'))) {
                $role->remark = $remark;
            }

            $role->save();

            if (null !== ($permissions = $request->get('permissions')) && is_array($permissions)) {
                $permissions = array_unique($permissions);
                $role->syncPermissions($permissions);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();

            $this->response->errorBadRequest($e->getMessage());
        }

        return $this->response->created(null, $role);
    }

    public function list(Request $request)
    {

        return $this->response->array(
            Role::query()
                ->withoutGlobalScope('status')
                ->when($request->get('status'), function (Builder $query, $status) {
                    $query->where('status', $status);
                })
                ->when($request->get('name'), function (Builder $query, $name) {
                    $query->where('name', 'like', '%' . $name . '%');
                })
                ->when($request->get('select'), function (Builder $query, $select) {
                    $query->select(explode(',', $select));
                })
                // 这里 withCount 得在 select 后, 不然会连表查询错误
                ->when($request->get('user_statistics', true), function (Builder $query) {
                    $query->withCount('users');
                })
                ->paginate());
    }

    public function info($id)
    {
        try {
            $role = Role::query()
                ->withoutGlobalScope('status')
                ->with('permissions:name')
                ->findOrFail($id);
        } catch (\Exception $e) {
            $this->response->errorBadRequest($e->getMessage());
        }

        return $this->response->array($role->toArray());
    }
}
